/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jpgaclusterwonetwork;

import java.util.BitSet;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.baatar.opt.genetic.AlgorithmParameters;
import org.baatar.opt.genetic.selection.BinaryTournamentSelection;
import org.baatar.opt.genetic.set.covering.binary.SCChromosomeFactory;
import org.baatar.opt.genetic.set.covering.binary.SCCrossover;
import org.baatar.opt.genetic.set.covering.binary.SCImprover;
import org.baatar.opt.genetic.set.covering.binary.SCMutator;
import org.baatar.opt.genetic.set.meta.DataSet;
import org.baatar.opt.pga.impl.service.Cluster;
import org.baatar.opt.pga.impl.service.PGAClusterServiceImpl;
import org.baatar.opt.pga.impl.service.PGACoordinatorServiceImpl;
import org.baatar.util.XMLUtil;

/**
 *
 * @author Ba
 */
public class SCPGAClusterSA {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws Exception {
        /**
         * Read cluster info from configuration file.
         */
long nano = System.nanoTime();
        int portNr = Integer.valueOf(XMLUtil.readProperty("pgacluster.xml", "pgaCluster", "portNr"));
        Integer numOfWorkers = Integer.valueOf(XMLUtil.readProperty("pgacluster.xml", "pgaCluster", "numOfWorkers"));

        String inputXmlFileName = XMLUtil.readProperty("pgacluster.xml", "pgaCluster", "inputFile");
        DataSet dataSet = org.baatar.opt.genetic.set.util.XMLUtil.readSetOptimizationInputDataFromXML(inputXmlFileName);
//        dataSet.init();
//dataSet.writeMatlabCode();
//int sol[] = new int[]{
//    25, 55, 73, 118, 130, 159, 171, 180, 181, 190, 208, 214, 236, 237, 244, 248, 261, 280, 290, 295, 304, 344, 395, 424, 427, 432, 447, 452, 462, 496, 510, 527, 533, 537, 543, 546, 
//569, 577, 589, 592, 597, 606, 647, 664, 697, 719, 721, 741, 744, 752, 764, 786, 796, 799, 816, 831, 833, 837, 839, 888, 897, 939, 943, 969, 973, 978, 998, 1015, 1025, 1044, 
//1058, 1075, 1083, 1090, 1115, 1123, 1135, 1138, 1141, 1150, 1191, 1208, 1241, 1263, 1265, 1285, 1288, 1294, 1308, 1327, 1337, 1340, 1357, 1372, 1374, 1378, 1380, 1430, 1439, 
//1482, 1486, 1512, 1516, 1521, 1536, 1541, 1558, 1568, 1587, 1601, 1617, 1621, 1625, 1631, 1632, 1657, 1665, 1669, 1680, 1683, 1689, 1693, 1733, 1763, 1784, 1808, 1828, 1831, 
//1838, 1850, 1861, 1879, 1882, 1899, 1914, 1916, 1920, 1922, 1929, 1972, 1976, 2000, 2012, 2025, 2031, 2056, 2063, 2080, 2086, 2087, 2103, 2125, 2139, 2155, 2159, 2164, 2170, 
//2171, 2195, 2201, 2204, 2215, 2218, 2224, 2228, 2261, 2297, 2318, 2320, 2342, 2362, 2365, 2374, 2384, 2395, 2413, 2416, 2433, 2448, 2450, 2454, 2463, 2506, 2510, 2540, 2551, 
//2559, 2565, 2590, 2600, 2617, 2618, 2622, 2638, 2660, 2674, 2695, 2699, 2706, 2730, 2739, 2750, 2753, 2763, 2806, 2839, 2862, 2888, 2908, 2914, 2920, 2932, 2941, 2961, 2964, 
//2980, 2990, 3004, 3014, 3057, 3091, 3097, 3110, 3116, 3144, 3145, 3151, 3170, 3174, 3175, 3196, 3212, 3224, 3243, 3248, 3252, 3259, 3264, 3277, 3289, 3302, 3345, 3384, 3390, 
//3392, 3402, 3410, 3429, 3444, 3470, 3488, 3495, 3513, 3520, 3529, 3532
//};
//System.out.print("Matlab cost = " + dataSet.calculateSolutionCost(sol));

//        for (int i = 0; i < 3; i++) {

//            PGACoordinatorServiceImpl<Boolean, BitSet> pgaCoordSrvImpl = new PGACoordinatorServiceImpl<>();
//            pgaCoordSrvImpl.initialize();
//            pgaCoordSrvImpl.setLogger(Logger.getLogger("coord"));
//            Logger.getLogger("coord").addAppender(new ConsoleAppender(new PatternLayout()));

            /**
             * Create implementation class and remoting service class.
             */
            PGAClusterServiceImpl<Boolean, BitSet> pgaClusterSrvImpl = new PGAClusterServiceImpl<>();
            pgaClusterSrvImpl.addNeighbor(pgaClusterSrvImpl);

//            pgaClusterSrvImpl.setCoordinator(pgaCoordSrvImpl);

            if (pgaClusterSrvImpl.initialize()) {

                /**
                 * Assign Logger.
                 */
                pgaClusterSrvImpl.setLogger(Logger.getLogger("cluster"));
                Logger.getLogger("cluster").addAppender(new ConsoleAppender(new PatternLayout()));

//                pgaCoordSrvImpl.addCluster(new Cluster<>(pgaClusterSrvImpl, 0, numOfWorkers));
//                pgaCoordSrvImpl.start();

                /**
                 * Start cluster service.
                 */
                if (pgaClusterSrvImpl.start()) {
                    pgaClusterSrvImpl.setNumOfWorkers(numOfWorkers);

                    /**
                     * Set algorithm preferences.
                     */
                    AlgorithmParameters<Boolean, BitSet> algoParams = new AlgorithmParameters<>();

                    algoParams.setMaxNumOfIterations(10000);
                    algoParams.setMaxNumOfIterationsWOProgress(5000);
                    algoParams.setPopulationSize(50);
                    algoParams.setMinNumOfChildren(12);
                    algoParams.setNumOfEliteChromosomes(4);
                    algoParams.setMutationRate(0.01f);   //  (float) (dataSet.rows.size() / (10.0 * dataSet.columns.size())));
                    algoParams.setGreedRate(0.03f);
                    algoParams.setAllowDublicateChromosomes(false);

                    algoParams.setMigrationRate(4);
                    algoParams.setMigrationFreq(10);
//                    algoParams.setMigrationRate(0);
//                    algoParams.setMigrationFreq(0);

                    algoParams.setChromosomeFactory(new SCChromosomeFactory(dataSet));
                    algoParams.setSelector(new BinaryTournamentSelection<Boolean, BitSet>());
                    algoParams.setCrossoverOperator(new SCCrossover());
                    algoParams.setMutator(new SCMutator(dataSet.columns.length,
                                                        dataSet.rows.length / 2.0,
                                                        500,
                                                        0.8));
                    algoParams.setImprover(new SCImprover(dataSet));

                    pgaClusterSrvImpl.setAlgoParams(algoParams);

                    pgaClusterSrvImpl.prepareOptimizers();
System.out.println("System is prepared in " + (System.nanoTime() - nano) / 1000000000.0 + " secs.");
                    pgaClusterSrvImpl.runOptimizers();
//                    pgaClusterSrvImpl.waitForOptimizers();
                }
            }
//        }
    }
}
